home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.3 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  9.0 KB  |  327 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 5.3: Brave Bob vs. Dragon                        //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include <vector>
  9. #include "debug.h"
  10. #include "mouse.h"
  11. #include "object.h"
  12. #include "camera.h"
  13.  
  14. class APPLICATION
  15. {
  16.     public:
  17.         APPLICATION();
  18.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  19.         HRESULT Update(float deltaTime);
  20.         HRESULT Render();
  21.         HRESULT Cleanup();
  22.         HRESULT Quit();
  23.  
  24.     private:
  25.         IDirect3DDevice9* m_pDevice; 
  26.         std::vector<OBJECT> m_objects;
  27.         CAMERA m_camera;
  28.         MOUSE m_mouse;
  29.  
  30.         int m_intersectType;
  31.         D3DLIGHT9 m_light;
  32.         HWND m_mainWindow;
  33.         ID3DXFont *m_pFont, *m_pFontMouse;
  34. };
  35.  
  36. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  37. {
  38.     APPLICATION app;
  39.  
  40.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  41.         return 0;
  42.  
  43.     MSG msg;
  44.     memset(&msg, 0, sizeof(MSG));
  45.     int startTime = timeGetTime(); 
  46.  
  47.     while(msg.message != WM_QUIT)
  48.     {
  49.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  50.         {
  51.             ::TranslateMessage(&msg);
  52.             ::DispatchMessage(&msg);
  53.         }
  54.         else
  55.         {    
  56.             int t = timeGetTime();
  57.             float deltaTime = (t - startTime)*0.001f;
  58.  
  59.             app.Update(deltaTime);
  60.             app.Render();
  61.  
  62.             startTime = t;
  63.         }
  64.     }
  65.  
  66.     app.Cleanup();
  67.  
  68.     return msg.wParam;
  69. }
  70.  
  71. APPLICATION::APPLICATION()
  72. {
  73.     m_pDevice = NULL; 
  74.     m_mainWindow = 0;
  75.     m_intersectType = 0;
  76.     m_pFont = m_pFontMouse = NULL;
  77.  
  78.     srand(GetTickCount());
  79. }
  80.  
  81. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  82. {
  83.     debug.Print("Application initiated");
  84.  
  85.     //Create Window Class
  86.     WNDCLASS wc;
  87.     memset(&wc, 0, sizeof(WNDCLASS));
  88.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  89.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  90.     wc.hInstance     = hInstance;
  91.     wc.lpszClassName = "D3DWND";
  92.  
  93.     //Register Class and Create new Window
  94.     RegisterClass(&wc);
  95.     m_mainWindow = CreateWindow("D3DWND", "Example 5.3: Brave Bob vs. Dragon (a.k.a. Picking Example)", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  96.     SetCursor(NULL);
  97.     ShowWindow(m_mainWindow, SW_SHOW);
  98.     UpdateWindow(m_mainWindow);
  99.  
  100.     //Create IDirect3D9 Interface
  101.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  102.  
  103.     if(d3d9 == NULL)
  104.     {
  105.         debug.Print("Direct3DCreate9() - FAILED");
  106.         return E_FAIL;
  107.     }
  108.  
  109.     //Check that the Device supports what we need from it
  110.     D3DCAPS9 caps;
  111.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  112.  
  113.     //Hardware Vertex Processing or not?
  114.     int vp = 0;
  115.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  116.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  117.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  118.  
  119.     //Check vertex & pixelshader versions
  120.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  121.     {
  122.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  123.     }
  124.  
  125.     //Set D3DPRESENT_PARAMETERS
  126.     D3DPRESENT_PARAMETERS d3dpp;
  127.     d3dpp.BackBufferWidth            = width;
  128.     d3dpp.BackBufferHeight           = height;
  129.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  130.     d3dpp.BackBufferCount            = 1;
  131.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  132.     d3dpp.MultiSampleQuality         = 0;
  133.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  134.     d3dpp.hDeviceWindow              = m_mainWindow;
  135.     d3dpp.Windowed                   = windowed;
  136.     d3dpp.EnableAutoDepthStencil     = true; 
  137.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  138.     d3dpp.Flags                      = 0;
  139.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  140.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  141.  
  142.     //Create the IDirect3DDevice9
  143.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  144.                                  vp, &d3dpp, &m_pDevice)))
  145.     {
  146.         debug.Print("Failed to create IDirect3DDevice9");
  147.         return E_FAIL;
  148.     }
  149.  
  150.     //Release IDirect3D9 interface
  151.     d3d9->Release();
  152.  
  153.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  154.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  155.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  156.  
  157.     D3DXCreateFont(m_pDevice, 24, 0, 0, 1, false,  
  158.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  159.                    DEFAULT_PITCH | FF_DONTCARE, "Arial Black", &m_pFontMouse);
  160.  
  161.     //Create m_light
  162.     ::ZeroMemory(&m_light, sizeof(m_light));
  163.     m_light.Type      = D3DLIGHT_DIRECTIONAL;
  164.     m_light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  165.     m_light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
  166.     m_light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  167.     m_light.Direction = D3DXVECTOR3(0.7f, -0.3f, 0.0f);
  168.     m_pDevice->SetLight(0, &m_light);
  169.     m_pDevice->LightEnable(0, true);
  170.  
  171.     //Set sampler state
  172.     for(int i=0;i<4;i++)
  173.     {
  174.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  175.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  176.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  177.     }
  178.  
  179.     //Init m_camera
  180.     m_camera.Init(m_pDevice);
  181.  
  182.     //Load objects
  183.     LoadObjectResources(m_pDevice);
  184.  
  185.     m_objects.push_back(OBJECT(DRAGON, D3DXVECTOR3(0.0f, 0.0f, 1.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(1.0f, 1.0f, 1.0f)));
  186.     m_objects.push_back(OBJECT(BOB, D3DXVECTOR3(0.0f, 0.0f, -1.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(1.0f, 1.0f, 1.0f)));
  187.     m_objects.push_back(OBJECT(RING, D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(1.0f, 1.0f, 1.0f)));
  188.  
  189.     //Init m_mouse
  190.     m_mouse.InitMouse(m_pDevice, m_mainWindow);
  191.  
  192.     return S_OK;
  193. }
  194.  
  195. HRESULT APPLICATION::Update(float deltaTime)
  196. {
  197.     //Set World matrix
  198.     D3DXMATRIX  matWorld;
  199.     D3DXMatrixIdentity(&matWorld);
  200.     m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
  201.  
  202.     //Update m_mouse
  203.     m_mouse.Update();
  204.  
  205.     //Update m_camera
  206.     m_camera.Update(m_mouse, deltaTime);
  207.  
  208.     //Change intersection test type
  209.     if(KEYDOWN(VK_SPACE))
  210.     {
  211.         Sleep(300);
  212.         m_intersectType++;
  213.         if(m_intersectType > 2)m_intersectType = 0;
  214.     }    
  215.  
  216.     if(KEYDOWN(VK_ESCAPE))
  217.         Quit();
  218.  
  219.     return S_OK;
  220. }    
  221.  
  222. HRESULT APPLICATION::Render()
  223. {
  224.     // Clear the viewport
  225.     m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );
  226.     
  227.     // Begin the scene 
  228.     if(SUCCEEDED(m_pDevice->BeginScene()))
  229.     {
  230.         for(int i=0;i<m_objects.size();i++)
  231.             m_objects[i].Render();
  232.         
  233.         //Find intersecting object closest to the camera
  234.         D3DXMATRIX identity;
  235.         D3DXMatrixIdentity(&identity);
  236.  
  237.         int object = -1;
  238.         float bestDist = 100000.0f;
  239.         for(int i=0;i<m_objects.size() - 1;i++)
  240.         {
  241.             float dist = -1.0f; 
  242.             
  243.             //Do intersection tests
  244.             if(m_intersectType == 0)
  245.             {
  246.                 m_pDevice->SetTransform(D3DTS_WORLD, &m_objects[i].m_meshInstance.GetWorldMatrix());
  247.                 RAY ray = m_mouse.GetRay();
  248.                 dist = ray.Intersect(m_objects[i].m_meshInstance);
  249.             }
  250.             else if(m_intersectType == 1)
  251.             {                
  252.                 m_pDevice->SetTransform(D3DTS_WORLD, &identity);
  253.                 RAY ray = m_mouse.GetRay();
  254.                 dist = ray.Intersect(m_objects[i].m_BBox);
  255.             }
  256.             else if(m_intersectType == 2)
  257.             {
  258.                 m_pDevice->SetTransform(D3DTS_WORLD, &identity);
  259.                 RAY ray = m_mouse.GetRay();
  260.                 dist = ray.Intersect(m_objects[i].m_BSphere);
  261.             }
  262.  
  263.             m_objects[i].RenderBoundingVolume(m_intersectType);
  264.  
  265.             if(dist >= 0.0f && dist < bestDist)
  266.             {
  267.                 object = i;
  268.                 bestDist = dist;
  269.             }
  270.         }
  271.  
  272.         //Write m_mouse text
  273.         if(object != -1)
  274.         {
  275.             RECT mr[] = {{m_mouse.x + 2, m_mouse.y + 24, 0, 0}, {m_mouse.x, m_mouse.y + 22, 0, 0}};
  276.             m_pFontMouse->DrawText(NULL, m_objects[object].m_name.c_str(), -1, &mr[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xff000000);
  277.             m_pFontMouse->DrawText(NULL, m_objects[object].m_name.c_str(), -1, &mr[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffff0000);
  278.         }
  279.  
  280.         RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}, {10, 50, 0, 0}};
  281.         m_pFont->DrawText(NULL, "Mouse Wheel: Change Camera Radius", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  282.         m_pFont->DrawText(NULL, "Arrows: Change Camera Angle", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  283.         m_pFont->DrawText(NULL, "Space: Change Bounding Volume", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  284.  
  285.         RECT rc = {500, 10, 0, 0};
  286.         if(m_intersectType == 0)
  287.             m_pFont->DrawText(NULL, "Mesh Intersection Test", -1, &rc, DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  288.         else if(m_intersectType == 1)
  289.             m_pFont->DrawText(NULL, "Box Intersection Test", -1, &rc, DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  290.         else if(m_intersectType == 2)
  291.             m_pFont->DrawText(NULL, "Sphere Intersection Test", -1, &rc, DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  292.         
  293.         //Draw m_mouse
  294.         m_mouse.Paint();
  295.  
  296.         // End the scene.
  297.         m_pDevice->EndScene();
  298.         m_pDevice->Present(0, 0, 0, 0);
  299.     }
  300.  
  301.     return S_OK;
  302. }
  303.  
  304. HRESULT APPLICATION::Cleanup()
  305. {
  306.     try
  307.     {
  308.         m_pFont->Release();
  309.         m_pFontMouse->Release();
  310.  
  311.         m_objects.clear();
  312.  
  313.         m_pDevice->Release();
  314.  
  315.         debug.Print("Application terminated");
  316.     }
  317.     catch(...){}
  318.  
  319.     return S_OK;
  320. }
  321.  
  322. HRESULT APPLICATION::Quit()
  323. {
  324.     ::DestroyWindow(m_mainWindow);
  325.     ::PostQuitMessage(0);
  326.     return S_OK;
  327. }